#include <stdio.h>


//树的边的结构体
struct LinkList
{
    //节点编号
    int index;
    //所有连接节点的边 包括根节点
    LinkList* next;
    LinkList* pre;
};

void deleteLinkList(LinkList* l)
{
    LinkList* next=l;
    while (next!=NULL)
    {
        LinkList* now=next->next;
        delete next;
        next=now;
    }
}

void addLinkList(LinkList** ev,int index,LinkList* l)
{
    if(ev[index]==NULL)
    {
        l->next=NULL;
        l->pre=NULL;
        ev[index]=l;
    }
    else{
        l->next=ev[index];
        l->pre=NULL;
        ev[index]->pre=l;
        ev[index]=l;
    }
}

int maxValue(int a,int b)
{
    return a>b?a:b;
}


int main(){
    int n;
    scanf("%d",&n);
    //储存节点分数
    int* input=new int[n];
    //储存DP结果
    int* result=new int[n];
    //DP时候记录该节点是否已经完成计算 
    int* isUse=new int[n];
    //记录树
    LinkList** ev=new LinkList*[n];
    //DP的时候记录遍历到了哪条边
    LinkList** stackList=new LinkList*[n];
    int i;

    //节点的最大值  处理特殊情况 节点分数全为负数的时候
    int max=-2147483647;

    for(i=0;i<n;i++)
    {
        scanf("%d",&input[i]);
        result[i]=input[i];
        isUse[i]=0;

        if(input[i]>max)
        {
            max=input[i];
        }

        ev[i]=NULL;
        stackList[i]=NULL;
    }

    int tmp1,tmp2;
    for(i=0;i<n-1;i++)
    {
        scanf("%d %d",&tmp1,&tmp2);
        tmp1--;
        tmp2--;

        //添加双向边
        LinkList* l=new LinkList;
        l->index=tmp2;
        addLinkList(ev,tmp1,l);

        l=new LinkList;
        l->index=tmp1;
        addLinkList(ev,tmp2,l);
    }

    int resultValue=max;

    int** stack=new int*[n];
    
    //把第一个节点当成根节点 入栈开始DP
    int len=0;
    //0存储当前节点 1存储当前节点的根节点
    stack[len]=new int[2];
    stack[len][0]=0;
    stack[len][1]=-1;
    len++;
    while (len>0)
    {
        LinkList* l;
        //根节点
        int rootIndex=stack[len-1][1];
        //当前节点
        int index=stack[len-1][0];

        //如果已经开始遍历 从上次遍历的边位置继续遍历
        if(stackList[len-1]!=NULL)
        {
            l=stackList[len-1];
        }
        //否则从头开始遍历
        else{
            l=ev[stack[len-1][0]];
        }

        while (l!=NULL)
        {
            if(l->index!=rootIndex)
            {   
                //子节点已经计算分数完成 累加子节点结果
                if(isUse[l->index])
                {
                    result[index]+=maxValue(result[l->index],0);
                }
                //否则跳出 
                else{
                    break;
                }
            }
            l=l->next;
        }

        //计算完毕 出栈
        if(l==NULL)
        {
            isUse[index]=1;
            stackList[len-1]=NULL;
            delete stack[len-1];
            len--;

            if(resultValue<result[index])
            {
                resultValue=result[index];
            }
        }
        //遍历子结点  子节点入栈
        else{
            //存储当前遍历位置
            stackList[len-1]=l;
            len++;
            stack[len-1]=new int[2];
            stack[len-1][0]=l->index;
            stack[len-1][1]=index;
        }
        
    }
    
    delete stack;
    delete stackList;

    delete input;
    delete result;
    for(i=0;i<n;i++)
    {
        deleteLinkList(ev[i]);
    }
    delete ev;

    if(resultValue==0&&max<0)
    {
        printf("%d\n",max);
    }
    else{
        printf("%d\n",resultValue);
    }
}